import { useRequest } from 'ahooks';
import { Options } from 'ahooks/lib/useRequest/src/types';
import { notification } from 'antd';
import axios, { AxiosRequestConfig } from 'axios';

import { apiDomain } from '@/config';
import { getRecoilOfUser } from '@/store/user';

import { ApiPathAndParam, ApiPostBody, ApiResponse, ExactPathByHttpMethod } from './utils';
export * from './utils';

const instance = axios.create({
  baseURL: apiDomain
});

instance.interceptors.request.use((config) => {
  const user = getRecoilOfUser();

  const authorizationHeaders = user.token ? { Authorization: `Bearer ${user.token}` } : {};

  return {
    ...config,
    headers: {
      ...config.headers,
      'Content-Type': 'application/json',
      ...authorizationHeaders
    } as any,
    url: config.url?.replace(/{([^}]*)}/g, (_, key) => {
      if (config.params) {
        const val = config.params[key];
        // delete config.params[key];
        return val;
      }
      if (config.data) {
        const val = config.data[key];
        // delete config.data[key];
        return val;
      }
      return '';
    })
  };
});

instance.interceptors.response.use((response) => {
  if (response.data.code === 0) {
    return response.data.data;
  } else {
    notification.error({ showProgress: true, message: response.data.msg });
  }

  return Promise.reject(response.data);
});

export function get<U extends ExactPathByHttpMethod<'get'>, P extends ApiPathAndParam<'get', U>>(url: U, params: P) {
  return instance.get<P, ApiResponse<'get', U>>(url, { params });
}

export function post<U extends ExactPathByHttpMethod<'post'>, D extends ApiPathAndParam<'post', U> | ApiPostBody<U>>(
  url: U,
  config?: AxiosRequestConfig<D>
) {
  return instance.post<D, ApiResponse<'post', U>>(url, config?.data || {}, config);
}

export function usePost<U extends ExactPathByHttpMethod<'post'>, P extends ApiPathAndParam<'post', U> | ApiPostBody<U>>(
  url: U,
  config?: AxiosRequestConfig<P>,
  useRequestOptions?: Options<ApiResponse<'post', U>, [P]>
) {
  return useRequest((requestParams: P) => {
    return post(url, {
      params: requestParams,
      data: requestParams,
      ...config
    });
  }, useRequestOptions);
}

export function useGet<U extends ExactPathByHttpMethod<'get'>, P extends ApiPathAndParam<'get', U>>(
  url: U,
  params: P,
  useRequestOptions?: Options<ApiResponse<'get', U>, [P]>
) {
  return useRequest((requestParams: P) => {
    return get(url, requestParams || params);
  }, useRequestOptions);
}

// const { data } = usePost('/group/{group}/rename', {
//   groupName: '',
//   groupDesc: 1
// });

// export function useGet(...params: Parameters<typeof client.GET>) {
//   return client.GET(...params);
// };

// const { data } = useGet('/api/get', {
//   id: 1
// });
// const { data: ab } = post('/group/{group}/rename', {
//   groupName: '',
//   groupDesc: 1
// });

// const { data: ab1 } = usePost('/flow/addGraph', {
//   flowId: 2
// });

// const a = {} as ApiQueryParam<'get', '/flow-result/exec-result/detail'>;

// const b = {} as ApiPathAndParam<'post', '/group/{group}/rename'>;

// const c = {} as ApiPathParam<'post', '/flow/{flowId}/execute'>;

// const d = {} as ApiBody<'post', '/flow/addGraph'>;
